<?php


namespace app\api\services;

use app\common\libs\Singleton;
use app\common\models\Marketing\Lottery;
use app\common\models\Marketing\LotteryAward;
use app\common\models\Marketing\LotteryData;
use app\common\models\Marketing\LotteryLog;
use app\common\models\Marketing\LotteryMember;
use app\common\models\Marketing\LotteryMemberAmountLog;
use app\common\models\Member\Member;
use app\common\models\Member\MemberGxzLog;
use app\common\models\Member\MemberNum;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;

class LotteryService
{
    use Singleton;

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function lotteryData(): array
    {
        $where = [
            ['status', '=', 1],
            ['is_switch', '=', 1],
            ['deleted', '=', 0],
        ];
        $lottery = Lottery::getInstance()->where($where)->find();
        if (empty($lottery)) {
            return [];
        }
        $now = date('Y-m-d H:i:s');
        if ($now < $lottery['startTime'] || $now > $lottery['endTime']) {
            return [];
        }
        if($lottery['isShow'] == 0){
            return [];
        }
        $list = LotteryData::getInstance()
            ->alias('l')
            ->leftJoin('member m', 'l.user_id=m.id')
            ->where('l.deleted', '=', 0)
            ->where('l.is_win', '=', 1)
            ->field('m.user_name,m.avatar,l.create_at,l.award_title')
            ->limit(30)
            ->order('l.id desc')
            ->select();
        return !empty($list) ? $list->toArray() : [];
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function awardList(): array
    {
        $where = [
            ['deleted', '=', 0]
        ];
        $lottery = Lottery::getInstance()->where($where)->find();
        if (empty($lottery)) {
            return [];
        }
        $lottery->browse_count++;
        $lottery->save();
        $where = [
            ['lottery_id', '=', $lottery['id']],
            ['status', '=', 1],
            ['deleted', '=', 0],
        ];
        $lotteryAward = LotteryAward::getInstance()->where($where)->select();
        return !empty($lotteryAward) ? $lotteryAward->toArray() : [];
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function userLotteryList($userId, $page, $pageSize): array
    {
        $where = [
            ['l.deleted', '=', 0],
            ['l.user_id', '=', $userId],
            ['l.is_win','=',1]
        ];
        $list = LotteryData::getInstance()
            ->alias('l')
            ->leftJoin('member m', 'l.user_id=m.id')
            ->where($where)
            ->field('m.user_name,m.avatar,l.create_at,l.award_title,l.balance,l.is_send')
            ->page($page, $pageSize)
            ->order('l.id desc')
            ->select();
        return !empty($list) ? $list->toArray() : [];
    }

    /**
     * 赠送抽奖次数
     * $type 0商户入驻 1会员入驻 2支付订单
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function send($userId, $type = 0, $money = 0, $orderNo = ''): bool
    {
        $where = [
            ['status', '=', 1],
            ['is_switch', '=', 1],
            ['deleted', '=', 0],
        ];
        $lottery = Lottery::getInstance()->where($where)->find();
        if (empty($lottery)) {
            return false;
        }
        $now = date('Y-m-d H:i:s');
        if ($now < $lottery['startTime'] || $now > $lottery['endTime']) {
            return false;
        }
        //0贡献值 1指定任务
        if($lottery['joinType'] == 1){
            if(empty($lottery['taskType'])){
               return false;
            }
            $taskType = json_decode($lottery['taskType'],true);
            if(in_array(1,$taskType) && $type == 2){
                if($money >= $lottery['orderFullMoney']){
                    $this->addLotteryNum($userId,$lottery['orderFullCount'],'order',$type,1,$orderNo);
                    return true;
                }
            }
            //推荐会员
            if(in_array(3,$taskType) && $type == 1){
                if(!empty($lottery['activeType'])){
                    $activeArr = json_decode($lottery['activeType'],1);
                    if(in_array(1,$activeArr) && $lottery['directUserMin'] > 0){
                        if($money < $lottery['directUserMin']){
                            return false;
                        }
                    }
                }
                if($lottery['directUser'] > 1){
                    $where = [
                        ['user_id','=',$userId],
                        ['type','=',$type],
                    ];
                    $createAt = LotteryLog::getInstance()->where($where)->order('id desc')->value('create_at');
                    if($createAt){
                        $where = [
                            ['invite_id','=',$userId],
                            ['create_at','>',$createAt],
                        ];
                    }else{
                        $where = [
                            ['invite_id','=',$userId],
                            ['create_at','>=',$lottery['startTime']],
                        ];
                    }
                    $inviteCount = Member::getInstance()->where($where)->count();
                    if($inviteCount >= $lottery['directUser']){
                        $this->addLotteryNum($userId,$lottery['directUserCount'],'direct_user',$type,1);
                    }
                }else{
                    $this->addLotteryNum($userId,$lottery['directUserCount'],'direct_user',$type,1);
                }
                return true;
            }

        }
        return false;
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function inviteUserConsume($userId, $type, $money, $orderNo): bool
    {
        $member = Member::getInstance()->where('id',$userId)->find();
        if(empty($member)){
            return false;
        }
        if(empty($member['inviteId'])){
            return false;
        }
        $where = [
            ['status', '=', 1],
            ['is_switch', '=', 1],
            ['deleted', '=', 0],
        ];
        $lottery = Lottery::getInstance()->where($where)->find();
        if (empty($lottery)) {
            return false;
        }
        $now = $member['createAt'];
        if ($now < $lottery['startTime'] || $now > $lottery['endTime']) {
            return false;
        }
        $this->send($member['inviteId'], $type, $money, $orderNo);
        return true;
    }


    /**
     * type 0商户入驻 1会员入驻 2支付订单
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function addLotteryNum($userId,$count,$logType,$type,$status,$orderNo = '',$msg = ''): bool
    {
        $finance = MemberInfoService::getInstance()->memberNum($userId);
        $thisAmount = $finance['lotteryCount'];

        if ($status == 1) {
            $alterAmount = bcadd($thisAmount, $count, 2);
        } else {
            $alterAmount = bcsub($thisAmount, $count, 2);
        }

        MemberNum::getInstance()->startTrans();
        try {
            $data = [
                'user_id'      => $finance['userId'],
                'status'       => $status,
                'remark'       => $msg,
                'log_type'     => $logType,
                'this_amount'  => $thisAmount,
                'alter_amount' => $alterAmount,
                'amount'       => $count,
                'order_no'     => $orderNo,
            ];
            LotteryMemberAmountLog::getInstance()->insert($data);
            if ($status == 1) {
                $data = [
                    'user_id' => $userId,
                    'type' => $type,
                    'count' => $count,
                ];
                LotteryLog::getInstance()->insert($data);
                MemberNum::getInstance()->where('user_id',$userId)->inc('lottery_count',$count)->update();
                MemberNum::getInstance()->where('user_id',$userId)->inc('lottery_total_count',$count)->update();
            } else {
                MemberNum::getInstance()->where('user_id',$userId)->dec('lottery_count',$count)->update();
                $this->updateLotteryLog($userId);
            }
            MemberNum::getInstance()->commit();
        }catch (\Exception $e){
            Log::error($e->getMessage());
            MemberNum::getInstance()->rollback();
            return false;
        }
        return true;
    }

    public function gxzLottery($userId, $lottery): bool
    {
        MemberGxzLog::getInstance()->startTrans();
        try{
            $this->updateLotteryLog($userId);
            $msg     = '抽奖扣除贡献值';
            MemberService::getInstance()->addFinanceLog(
                $userId, 'lottery_dec', $lottery['consumeGxz'], 7, $msg);
        }catch (\Exception $e){
            MemberGxzLog::getInstance()->rollback();
            return false;
        }
        MemberGxzLog::getInstance()->commit();
        return true;
    }

    public function noWin($userId,$count,$lottery): bool
    {
        LotteryData::getInstance()->startTrans();
        try{
            $data = [
                'user_id' => $userId,
                'is_win' => 0,
            ];
            LotteryData::getInstance()->insert($data);
            if($lottery['joinType'] == 0){
                $ret = $this->gxzLottery($userId,$lottery);
            }else{
                $ret = $this->addLotteryNum($userId,$count,'lottery',0,2);
            }
            if($ret === false){
                throw new \Exception('未中奖更新失败');
            }
        }catch (\Exception $e){
            LotteryData::getInstance()->rollback();
            return false;
        }
        LotteryData::getInstance()->commit();
        return true;
    }

    public function win($userId,$count,$lottery,$lotteryAward): bool
    {
        LotteryData::getInstance()->startTrans();
        try{
            //扣除库存
            $lotteryAward->remainNum--;
            $lotteryAward->save();
            //更新奖品用户
            $where = [
                ['deleted','=',0],
                ['status','=',0],
                ['lottery_award_id','=',$lotteryAward['id']],
                ['user_id','=',$userId]
            ];
            LotteryMember::getInstance()->where($where)->update(['status' => 1,'update_at' => date('Y-m-d H:i:s')]);
            $data = [
                'lottery_id' => $lottery['id'],
                'lottery_award_id' => $lotteryAward['id'],
                'user_id' => $userId,
                'gxz' => $lotteryAward['gxz'],
                'balance' => $lotteryAward['balance'],
                'award_title' => $lotteryAward['title'],
                'award_type' => $lotteryAward['awardType'],
                'is_win' => 1,
            ];
            if($lotteryAward['awardType'] == 1){
                //自动到账
                if($lottery['sendType'] == 0){
                    //余额
                    if($lottery['cashType'] == 0){
                        MemberService::getInstance()->addFinanceLog($userId, 'lottery_add', $lotteryAward['balance'], 1, '抽奖赠送现金红包');
                        $data['is_send'] = 1;
                        $data['send_time'] = date('Y-m-d H:i:s');
                    }else{
                        //电子钱包
                    }
                }
            }
            LotteryData::getInstance()->insert($data);
            if($lottery['joinType'] == 0){
                $ret = $this->gxzLottery($userId,$lottery);
            }else{
                $ret = $this->addLotteryNum($userId,$count,'lottery',0,2,'','');
            }
            if($ret === false){
                throw new \Exception('中奖更新失败');
            }
        }catch (\Exception $e){
            Log::error($e->getMessage().$e->getLine());
            LotteryData::getInstance()->rollback();
            return false;
        }
        LotteryData::getInstance()->commit();
        return true;
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function getLotteryAward($userId, $lottery){
        $where = [
            ['deleted','=',0],
            ['status','=',0],
            ['user_id','=',$userId]
        ];
        $lotteryMember = LotteryMember::getInstance()->where($where)->find();
        $where = [
            ['user_id','=',$userId],
        ];
        $count = LotteryData::getInstance()->where($where)->count()+1;
        if(!empty($lotteryMember['lotteryAwardId']) && $count == $lotteryMember['count']){
            $where = [
                ['id', '=', $lotteryMember['lotteryAwardId']],
                ['status', '=', 1],
                ['remain_num', '>', 0],
                ['deleted', '=', 0],
            ];
            $lotteryAward = LotteryAward::getInstance()->where($where)->find();
        }else{
            $where = [
                ['lottery_id', '=', $lottery['id']],
                ['status', '=', 1],
                ['deleted', '=', 0],
            ];
            $lotteryAwardList = LotteryAward::getInstance()->where($where)->order('sort asc')->select();
            $lotteryAward = null;
            $where = [
                ['user_id','=',$userId],
                ['is_used','=',0],
                ['type','in',[0,1]]
            ];
            $logCount = LotteryLog::getInstance()->where($where)->count();
            $rate = 0;
            $rand = mt_rand(1,100);
            foreach($lotteryAwardList as $v){
                $rate += $v['sort'];
                if($v['remain_num'] <= 0){
                    continue;
                }
                if($rand > $rate){
                    continue;
                }
                if($logCount > 0){
                    if($v['award_type'] == 0){
                        if($v['gxz'] > $lottery['inviteUserMax']){
                            continue;
                        }
                    }
                    if($v['award_type'] == 1){
                        if($v['balance'] > $lottery['inviteShopMax']){
                            continue;
                        }
                    }
                }

                $where = [
                    ['lottery_award_id','=',$v['id']],
                    ['deleted','=',0],
                    ['status','=',0],
                ];
                $count = LotteryMember::getInstance()->where($where)->count();
                //剩余次数大于名单数量
                if($v['remainNum'] > $count){
                    $lotteryAward = $v;
                    break;
                }
            }
        }
        return $lotteryAward;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function lotteryInfo(): array
    {
        $where = [
            ['status', '=', 1],
            ['is_switch', '=', 1],
            ['deleted', '=', 0],
        ];
        $lottery = Lottery::getInstance()->where($where)->find();
        if (empty($lottery)) {
            return [];
        }
        return $lottery->toArray();
    }

    /**
     * @param $userId
     * @return true
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function updateLotteryLog($userId): bool
    {
        $where = [
            ['user_id', '=', $userId],
            ['is_used', '=', 0],
            ['type', 'in', [0, 1]]
        ];
        $lotteryLog = LotteryLog::getInstance()->where($where)->order('id asc')->find();
        if ($lotteryLog) {
            $lotteryLog->isUsed = 1;
            $lotteryLog->updateAt = date('Y-m-d H:i:s');
            $lotteryLog->save();
        }
        return true;
    }

}